package dados;

import java.io.Serializable;
import java.util.*;

import sistema.Verificador;


import dados.FormaDeContato.TipoDeFormaDeContato;


/**
 * Classe Contato que possui nome,email,endereco,aniversario e uma ou mais formas de contato
 *
 */
public class Contato implements Serializable{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private String email,nome,endereco,aniversario,descricao;
	private List<FormaDeContato> formasdecontato;
	
	/**
	 * Cria um contato com nome e email.
	 * @param nome O nome do contato.
	 * @param email O emeil do Contato.
	 * @throws Exception Caso o nome for vazio ou o email invalido.
	 */
	public Contato(String nome,String email)throws Exception{
		if (Verificador.ehVazio(nome)){throw new Exception("Nome Vazio.");}
		if (!Verificador.ehEmailValido(email)){throw new Exception("Email Invalido.\nDigite na forma: nome@host");}
		formasdecontato = new ArrayList<FormaDeContato>();
		addFormaDeContato(TipoDeFormaDeContato.EMAIL, email);
		this.nome = nome;
		this.email = email;
		this.endereco = "";
		this.descricao = "";
		this.aniversario = "";
	}
	
	/**
	 * Cria um contato com nome, e-mail e endereco.
	 * @param nome O nome do Contato.
	 * @param email o e-mail do Contato.
	 * @param endereco o endereco do Contato.
	 * @throws Exception caso o endereco seja invalido ou o nome ou endereco estajam vazios.
	 */
	public Contato(String nome,String email,String endereco)throws Exception{
		this(nome, email);
		if (Verificador.ehVazio(endereco)){throw new Exception("Endereco Vazio");}
		this.endereco = endereco;
	}
	
	
	/**
	 * Cria um contato com nome, e-mail, aniversario e endereco.
	 * @param nome O nome do Contato.
	 * @param email o e-mail do Contato.
	 * @param endereco o endereco do Contato.
	 * @param aniversario a data de aniversario do Contato.
	 * @throws Exception caso o endereco seja invalido, o nome ou endereco estejam vazios, ou se a data for invalida.
	 */
	public Contato(String nome,String email,String endereco ,String aniversario )throws Exception{
		this(nome,email,endereco);
		if(!(Verificador.ehDataSemAnoValida(aniversario)|| Verificador.ehDataComAnoValida(aniversario))){throw new Exception("Data de Aniversario Invalida.\nDigite na forma: dd/mm/aaa");}
		this.aniversario = aniversario;
	}
	/**
	 * Retorna o e-mail do Contato.
	 * @return A String e-mail.
	 */
	public String getEmail() {
		return email;
	}
	/**
	 * Modifica o e-mail do Contato.
	 * @param email O novo e-mail.
	 */
	public void setEmail(String email) {
		this.email = email;
	}
	/**
	 * Retorna o endereco do contato.
	 * @return A String endereco.
	 */
	public String getEndereco() {
		return endereco;
	}
	/**
	 * Modifica o endereco do contato.
	 * @param endereco O novo endereco.
	 */
	public void setEndereco(String endereco) {
		this.endereco = endereco;
	}
	/**
	 * Retorna o aniversario do Contato
	 * @return a String Aniversario
	 */
	public String getAniversario() {
		return aniversario;
	}
	/**
	 * Modifica o aniversario do Contato
	 * @param aniversario o aniversario
	 * @throws Exception se data fpr invalida
	 */
	public void setAniversario(String aniversario) throws Exception {
		if(!(Verificador.ehDataSemAnoValida(aniversario)|| Verificador.ehDataComAnoValida(aniversario))){throw new Exception("Data de Aniversario Invalida.\nDigite na forma: dd/mm/aaa");}
		this.aniversario = aniversario;
	}
	/**
	 * Retorna o nome do Contato.
	 * @return A String nome.
	 */
	public String getNome() {
		return nome;
	}
	/**
	 * Retorna a descricao do contato.
	 * @return A String descricao.
	 */
	public String getDescricao(){
		return descricao;
	}
	/**
	 * Modifica a descricao do contato.
	 * @param descricao A nova descricao.
	 */
	public void setDescricao(String descricao){
		this.descricao = descricao;
	}
	/**
	 * Retorna as formas de contato de um contato
	 * @return
	 */
	public List<FormaDeContato> getFormasDeContato(){
		return formasdecontato;
	}
	/**
	 * Adiciona uma Forma de contato ao Contato.
	 * @param formaDeContato A forma de contato a ser adicionada.
	 */
	public void addFormaDeContato(FormaDeContato formaDeContato){
		formasdecontato.add(formaDeContato);
	}
	/**
	 * Adiciona uma Forma de contato ao Contato a partir de um nome e endereco.
	 * @param nome O nome da forma de contato. Ex: telefone.
	 * @param endereco o endereco da forma de contato. Ex: (11)3324-2323.
	 * @throws Exception Caso a forma de contato nao puder ser criada
	 */
	public void addFormaDeContato(TipoDeFormaDeContato tipo ,String endereco) throws Exception{
		FormaDeContato f = new FormaDeContato(tipo, endereco);
		formasdecontato.add(f);
	}
	/**
	 * Retorna as formas de contato que comecam com o nome passado.
	 * @param nome O nome a ser procurado nas FormasDeContato.
	 * @return Uma List<FormaDeContato>.
	 */
	public List<FormaDeContato> pesquisaFormaDeContato(TipoDeFormaDeContato tipo){
		List<FormaDeContato> formasDeContato = new ArrayList<FormaDeContato>();
		for(FormaDeContato f: getFormasDeContato()){
			if(f.getTipo().equals(tipo)){
				formasDeContato.add(f);
			}
		}
		return formasDeContato;
	}
	/**
	 * Remova uma FormaDeContato do Contato
	 * @param f a Forma de contato a ser romevida
	 * @return o sucesso ou nao da operacao.
	 */
	public boolean removeFormaDeContato(FormaDeContato f){
		return formasdecontato.remove(f);
	}
	/**
	 * Representacao em String de um contato.
	 */
	public String toString(){
		String string = getNome()+", "+getEmail();
		return string;
	}
	/**
	 * Compara igualdade entre dois contatos, dois contatos sao iguais se seus e-mails sao iguais.
	 */
	public boolean equals(Object obj){
		if (!(obj instanceof Contato)){return false;}
		Contato outro = (Contato) obj;
		return (getEmail().equalsIgnoreCase(outro.getEmail()));
	}
}
